﻿#include "FactorTable.h"
#include "LargeSampleSimulationUI.h"
#include <QToolBar>
#include <iostream>
#include <fstream>
#include <string>
#include <direct.h>
#include <io.h>
#include <sys/types.h>
#include "anova.h"
#include <algorithm>
#include <unordered_map>

//#include <QTextCodec>
//#include <QAxObject>

FactorTableWidget::FactorTableWidget(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	ui.tabWidget->setCurrentIndex(0);
	ui.tabWidget_2->setCurrentIndex(0);
	//ui.progressBar->setVisible(false);
	//ui.progressBar->setValue(0);
	ui.tableWidget->setRowCount(10);
	ui.tableWidget->setColumnCount(10);
	ui.tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//固定行高
	ui.tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//列宽填充
	//ui.tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//自适应列宽
	ui.tableWidget->setAlternatingRowColors(true);//隔行变色
	//ui.pushButton_5->setEnabled(false);             //测试

	//关闭窗口之后析构该类
	this->setAttribute(Qt::WA_DeleteOnClose);
	curTaskId = 0;
	curXDNums = 0;
	curDisplayId = 0;
	curSendWindowLen = 0;
	plot = new PlotPictureWidget;
	resNameList << QString::fromLocal8Bit("结果1")<< QString::fromLocal8Bit("结果2")<< QString::fromLocal8Bit("结果3")<< QString::fromLocal8Bit("结果4")<<
			QString::fromLocal8Bit("结果5")<< QString::fromLocal8Bit("结果6")<< QString::fromLocal8Bit("结果7")<< QString::fromLocal8Bit("结果8");	//结果名
	isGKDataLoad = false;
	ui.selectResBox->addItems(resNameList);
	pca = new PCAclass;
}

FactorTableWidget::~FactorTableWidget()
{
	if (plot)
		delete plot;
	if (modelAnova)
		delete modelAnova;
	if (pca)
		delete pca;
}


void FactorTableWidget::setUsersqlptr(Usersql* val)
{
	sql = val;
}


QString FactorTableWidget::getcurFolderPath()
{
	return curFolderPath;
}

int FactorTableWidget::getcurDisplayId()
{
	return curDisplayId;
}

//void FactorTableWidget::OnupdateGK(const int id, const QString &FilePath_GK)
//{
//	QString str_id(id);
//	this->sql_ft->updateGK(str_id, FilePath_GK);
//}
//void FactorTableWidget::OnupdateXD(const int id, const QString &FilePath_XD)
//{
//	QString str_id(id);
//	this->sql_ft->updateXD(str_id, FilePath_XD);
//}
//void FactorTableWidget::OnupdateRes(const int id, const QString &FilePath_Res)
//{
//	QString str_id(id);
//	this->sql_ft->updateRes(str_id, FilePath_Res);
//}
void FactorTableWidget::settaskStatusFinish()
{
	taskStatus = QString::fromLocal8Bit("计算完成");
	emit(changeTaskStatus(curTaskId, taskStatus));
}


void FactorTableWidget::OnActionOpenFactorLeveltable() 
{

	//桌面打开//Qt4
	//QString desktopDir=QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
	//Qt 5
	QString desktopDir = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
	//选择Excel文件，并获取路径
	QString path_FL = QFileDialog::getOpenFileName(NULL, "选择Excel", desktopDir, "*.xlsx *.xls");
	if (path_FL.isNull()) {
		QMessageBox::warning(NULL, QString::fromLocal8Bit("错误提示"), QString::fromLocal8Bit("无法打开excel文件"));
		return;
	}

	ui.lineEdit->setText(path_FL);

	//读取excel
	QSqlDatabase db = QSqlDatabase::addDatabase("QODBC", "excel");
	if (!db.isValid())
	{
		QMessageBox::warning(NULL, QString::fromLocal8Bit("错误提示"), QString::fromLocal8Bit("数据库驱动异常"));
		db.close();
		return;
	}

	QString dsn = QString("Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};Readonly=TRUE;DBQ=%1;").arg(path_FL);
	db.setDatabaseName(dsn);
	if (!db.open())
	{
		//QSqlError error= db.lastError();
		//QString str = error.text();
		QMessageBox::warning(NULL, QString::fromLocal8Bit("错误提示"), QString::fromLocal8Bit("无法打开数据库"));
		db.close();
		return;
	}
	QSqlQuery query(db);
	QString tableName = "Sheet1$"; //sheet名，$是必须的
	QString sql = "select * from [" + tableName + "]";
	query.exec(sql);

	//重新设置行、列数
	QSqlRecord rec = query.record();
	int cols = rec.count();
	ui.tableWidget->setColumnCount(cols);
	ui.tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//固定行高
	ui.tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//列宽自动填充
	//将因素名保存在factorNames中(excel第一行数据将作为数据库字段，因此遍历字段以获取因素名)
	for (int i = 0; i < cols; i++)
	{
		factorNames.push_back(rec.fieldName(i));
	}
	//设置表头为因素名
	ui.tableWidget->setHorizontalHeaderLabels(factorNames);


	//将从数据库查询到的数据显示在QTableWidget中
	//将数据保存的二维数组FactorLevelData中
	int row = 0; //行号
	FactorLevelData.clear();
	while (query.next())   	//每次query就是一行数据
	{
		if (row > ui.tableWidget->rowCount() - 1)
			ui.tableWidget->insertRow(row);
		std::vector<float> rowData;
		for (int i = 0; i < cols; i++)
		{
			float n = query.value(i).toDouble();
			rowData.push_back(n);
			QTableWidgetItem *item = new QTableWidgetItem(QString::number(query.value(i).toDouble(), 'f', 6));
			ui.tableWidget->setItem(row, i, item);
		}
		FactorLevelData.push_back(rowData);
		row++;
	}
	query.clear();
	db.close();
	taskStatus = QString::fromLocal8Bit("因素水平表已读");
}

//创建文件夹 先创建data文件夹 
//每次添加任务时在data文件夹下再创建一个以当前时间命名的文件夹 
//用来存放当前任务的工况表、想定表、结果表
int FactorTableWidget::CreatCurTaskDataFolder()
{
	char folderPath[100];
	char folderFullPath[200];
	sprintf(folderPath, ".\\data");
	if (access(folderPath, 0))
	{
		if (mkdir(folderPath) == -1)
		{
			//log.ERROR_log("时域积分结果文件创建失败");
			//ErrorHandlerFunction();
			return -1;
		}
	}
	QString datatime = QDateTime::currentDateTime().toString("yyyy.MM.dd.hh_mm_ss");
	sprintf(folderPath, ".\\data\\%s",datatime.toStdString().c_str());
	if (access(folderPath, 0))
	{
		if (mkdir(folderPath) == -1)
		{
			//log.ERROR_log("时域积分结果文件创建失败");
			//ErrorHandlerFunction();
			return -1;
		}
	}
	curFolderPath = folderPath;
	taskStatus = QString::fromLocal8Bit("任务文件夹已创建");
}

//生成并显示工况表
void FactorTableWidget::OnActionCreateGongKuang()
{
	ui.tabWidget->setCurrentIndex(1);
	if (taskStatus == QString::fromLocal8Bit("因素水平表已读")) {  
		CreatCurTaskDataFolder();
	}
	//生成工况表部分 生成的工况表以txt形式存储
	char buffer[200];
	getcwd(buffer, 200);
	std::string curpath(buffer);//得到当前运行目录
	std::string path_GK = curpath + curFolderPath.toStdString().erase(0,1) + "\\gk.txt";//得到工况表全路径（删掉了curFolderPath最前面的.）
	m_path_GK = QString::fromLocal8Bit(path_GK.c_str());

	std::ofstream ofs;
	std::string factorLevelPath = curpath + curFolderPath.toStdString().erase(0,1) + "\\factor_level_table.txt";
	ofs.open(factorLevelPath.c_str(), std::ios::out);

	for (int j = 0; j < factorNames.size(); j++)
	{
		std::string tmp = factorNames[j].toStdString() + ":";
		for (int i = 0; i < FactorLevelData.size(); i++)
		{
			tmp += std::to_string(FactorLevelData[i][j]) + " ";
		}
		ofs << tmp << "\n";
	}
	ofs.close();
	nCol = factorNames.size();
	//调用python,进行正交实验表生成
	std::string curpath_fol = curpath + curFolderPath.toStdString().erase(0, 1);
	m_TaskDataFolderPath = QString::fromStdString(curpath_fol);
	std::string command = "python " + curpath + "\\test2.py " + curpath_fol + "\\factor_level_table.txt " + path_GK+" oat";//全因子"full"
	system(command.c_str());

	taskStatus = QString::fromLocal8Bit("工况表已生成");

	//添加到数据库
	curTaskId = sql->getTaskListLastId() + 1;
	//QString str_id = QString::number(id);
	QString str_factorName = factorNames.join(" ");
	QString str_curpath_fol = QString::fromLocal8Bit(curpath_fol.c_str());
	//emit (updateTaskInfo(id, str_factorName, str_curpath_fol, QString::fromLocal8Bit("工况表已生成")));
	emit(updateTaskInfo(curTaskId, str_factorName, str_curpath_fol, taskStatus));


	//显示工况表
	OndisplayTxt_GK(m_path_GK);

}
void FactorTableWidget::OnActionCreateXiangding()   //生成并显示想定表
{
	ui.tabWidget->setCurrentIndex(2);

	/*生成想定部分 生成的想定以txt形式存储    更新想定表路径


    */
	taskStatus = QString::fromLocal8Bit("想定表已生成");
	emit(changeTaskStatus(curTaskId, taskStatus));
	m_path_XD = "C://Users//zhang//Desktop//LargeSampleSimulationUI_0630//LargeSampleSimulationUI//data//XD0.txt";      //测试用
	OndisplayTxt_XD(m_path_XD);

}

//显示因素水平表(读txt)
void FactorTableWidget::OndisplayTxt_FL(const QString &FilePath_FL)
{
	ui.lineEdit->setText(FilePath_FL);
	ui.tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//固定行高
	ui.tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//列宽自动填充

	QFile t_file(FilePath_FL);
	if (!t_file.open(QIODevice::ReadOnly))
	{
		QMessageBox::information(this, tr("information"), tr("File opening failed"));
		return;
	}
	QTextStream t_in(&t_file);
	QVector<QStringList> t_data;  //文件内容

	//读因素水平表txt
	while (!t_in.atEnd())
	{
		//分割":"与" "
		QString t_line = t_in.readLine();
		QString vars = t_line.split(':').last();
		QStringList var_list = vars.simplified().split(' ');	//去除vars中前后空格，再按空格分割
		t_data.append(var_list);
	}
	//设置表头为因素名
	ui.tableWidget->setRowCount(t_data[0].count());
	ui.tableWidget->setColumnCount(nCol);
	ui.tableWidget->setHorizontalHeaderLabels(factorNames);

	//表格内容
	for (int i = 0; i < t_data.size(); i++)
	{
		for (int j = 0; j < t_data[i].count(); j++)
		{
			ui.tableWidget->setItem(j, i, new QTableWidgetItem(t_data[i][j]));
		}
	}
}

//显示工况表(读txt)
void FactorTableWidget::OndisplayTxt_GK(const QString &FilePath_GK)
{       
	m_path_GK = FilePath_GK;
	ui.lineEdit_2->setText(m_path_GK);
	ui.tableWidget_2->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//固定行高
	ui.tableWidget_2->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//列宽自动填充
	ui.tableWidget_2->setAlternatingRowColors(true);//隔行变色

	QFile t_file(m_path_GK);
	if (!t_file.open(QIODevice::ReadOnly))
	{
		QMessageBox::information(this, tr("information"), tr("File opening failed"));
		return;
	}
	QTextStream t_in(&t_file);
	QVector<QStringList> t_data;  //文件内容

	//读第一行，更新因素列表
	QString t_line = t_in.readLine().simplified();
	QStringList t_list = t_line.split(' ');
	this->factorNames = t_list;
	this->nCol = t_list.size();

	int t_rowCount = 0;     //文件读取行数，同于设置表格行数
	while (!t_in.atEnd())
	{
		t_line = t_in.readLine();
		t_list = t_line.split(' ');
		t_data.append(t_list);
		t_rowCount++;
	}
	this->nCol = factorNames.size();
	this->curXDNums = t_rowCount;
	//设置表头为因素名
	ui.tableWidget_2->setRowCount(t_rowCount);
	ui.tableWidget_2->setColumnCount(nCol);
	ui.tableWidget_2->setHorizontalHeaderLabels(factorNames);

	//表格内容
	for (int i = 0; i < t_data.size(); i++)
	{
		std::vector<float> tmp(t_data[i].count());
		for (int j = 0; j < t_data[i].count(); j++)
		{
			tmp[j] = t_data[i][j].toFloat();
			ui.tableWidget_2->setItem(i, j, new QTableWidgetItem(t_data[i][j]));
		}
		if(!isGKDataLoad)
			GKData.emplace_back(std::move(tmp));
	}
	isGKDataLoad = true;
	
	//查询当前有没有结果，有结果则显示结果
	QString resultFileName = m_TaskDataFolderPath + "\\avr_res.txt";
	QFile res_file(resultFileName);

	//没有这个文件，说明没有结果，退出
	if (!res_file.open(QIODevice::ReadOnly))
	{
		return;
	}
	QTextStream res_in(&res_file);
	t_line.clear();
	t_list.clear();
	QVector<QStringList> res_data;  //结果文件内容
	while (!res_in.atEnd())
	{
		t_line = res_in.readLine().simplified();
		t_list = t_line.split(' ');
		res_data.append(t_list);
	}
	//若结果为空，退出
	if (res_data.empty())
		return;

	//插入新列
	int newInsertColNums = res_data[0].length();
	int oldColNum = ui.tableWidget_2->columnCount();
	for (int i = 0; i < newInsertColNums; i++)
	{
		ui.tableWidget_2->insertColumn(oldColNum + i);
	}
	//设置新表头
	QStringList resHead = { QString::fromLocal8Bit("结果1"),QString::fromLocal8Bit("结果2"), QString::fromLocal8Bit("结果3"), QString::fromLocal8Bit("结果4"),
		QString::fromLocal8Bit("结果5"), QString::fromLocal8Bit("结果6"), QString::fromLocal8Bit("结果7"), QString::fromLocal8Bit("结果8") };
	QStringList newHeadLabel = factorNames + resHead;
	ui.tableWidget_2->setHorizontalHeaderLabels(newHeadLabel);
	//显示结果
	for (int i = 0; i < res_data.size(); i++)
	{
		for(int j=0;j<newInsertColNums;j++)
			ui.tableWidget_2->setItem(i, oldColNum+j, new QTableWidgetItem(res_data[i][j]));
	}
}

//显示想定表(读txt)
void FactorTableWidget::OndisplayTxt_XD(const QString &FilePath_XD)
{
	if (taskStatus == QString::fromLocal8Bit("计算完成")) {
		ui.pushButton_5->setEnabled(true);
	}

	//m_path_XD = QFileDialog::getOpenFileName(this, tr("Open file"), "C:\\");
	m_path_XD = FilePath_XD;
	ui.lineEdit_3->setText(m_path_XD);
	ui.tableWidget_3->setAlternatingRowColors(true);//隔行变色
	ui.tableWidget_3->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//固定行高
	ui.tableWidget_3->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//列宽自动填充

	QFile t_file(m_path_XD);
	if (!t_file.open(QIODevice::ReadOnly))
	{
		QMessageBox::information(this, tr("information"), tr("File opening failed"));
		return;
	}
	QTextStream t_in(&t_file);
	int t_rowCount = 0;     //文件读取行数，同于设置表格行数
	QVector<QStringList> t_data;  //文件内容
	while (!t_in.atEnd())
	{
		QString t_line = t_in.readLine();
		QStringList t_list = t_line.split(' ');
		QString str = t_list[0];
		t_data.append(t_list);
		t_rowCount++;
	}
	this->curSendWindowLen = t_rowCount;//发送窗口长度，当前设置等于想定表行数
	QStringList t_headerList;
	int t_cloumCount = t_data[0].size();//设置表格列数
	
    ui.tableWidget_3->setRowCount(t_rowCount);
	ui.tableWidget_3->setColumnCount(t_cloumCount);
	
	//表头
	for (int i = 0; i < t_cloumCount; i++)
	{
		QString t_headerStr = "column" + QString::number(i + 1);
		t_headerList.append(t_headerStr);
	}
	ui.tableWidget_3->setHorizontalHeaderLabels(t_headerList);
	//表格内容
	for (int i = 0; i < t_data.size(); i++)
	{
		for (int j = 0; j < t_data[i].count(); j++)
		{
			ui.tableWidget_3->setItem(i, j, new QTableWidgetItem(t_data[i][j]));
		}
	}

	//最后一列插入数据回放按钮
	//如果此时显示的想定表还没有收到数据，则不加回放按钮
	QString resultFileName = m_TaskDataFolderPath + "\\res_plot_" + QString::number(curDisplayId) + ".txt";//注意！还没有为curDisplayId添加更新逻辑，此处默认是0
	QFile res_file(resultFileName);
	//没有这个文件，说明没有结果，退出
	if (!res_file.open(QIODevice::ReadOnly))
		return;
	QTextStream res_in(&res_file);
	QString t_line;
	QStringList t_list;
	QVector<QStringList> res_data;  //结果文件内容
	while (!res_in.atEnd())
	{
		t_line = res_in.readLine().simplified();
		t_list = t_line.split(' ');
		res_data.append(t_list);
	}
	//若结果为空，退出
	if (res_data.empty())
		return;

	//插入新列
	int newInsertColNums = res_data[0].length() + 1;
	int oldColNum = ui.tableWidget_3->columnCount();
	for (int i = 0; i < newInsertColNums; i++)
	{
		ui.tableWidget_3->insertColumn(oldColNum + i);
	}
	//设置新表头
	QStringList resHead = { QString::fromLocal8Bit("数据回放"),QString::fromLocal8Bit("结果1"),QString::fromLocal8Bit("结果2"), QString::fromLocal8Bit("结果3"), QString::fromLocal8Bit("结果4"),
		QString::fromLocal8Bit("结果5"), QString::fromLocal8Bit("结果6"), QString::fromLocal8Bit("结果7"), QString::fromLocal8Bit("结果8") };
	QStringList newHeadLabel = t_headerList + resHead;
	ui.tableWidget_3->setHorizontalHeaderLabels(newHeadLabel);
	//显示结果,并添加按钮
	for (int i = 0; i < res_data.size(); i++)
	{
		QPushButton *btn = new QPushButton(QString::fromLocal8Bit("数据回放"));
		//为按钮设置属性"row"，之后槽函数中可以根据调用对象的row来判断点击了第几行的按钮
		btn->setProperty("row", i);
		connect(btn, SIGNAL(clicked()), this, SLOT(OnActionPlotShow()));
		ui.tableWidget_3->setCellWidget(i, oldColNum, btn);
		for (int j = 0; j < res_data[0].length(); j++)
		{
			ui.tableWidget_3->setItem(i, oldColNum + 1 + j, new QTableWidgetItem(res_data[i][j]));
		}
			
	}
}

//显示结果表
void FactorTableWidget::OndisplayTxt_avr_res()
{
	ui.tableWidget_4->setAlternatingRowColors(true);//隔行变色
	ui.tableWidget_4->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//固定行高
	ui.tableWidget_4->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//列宽自动填充

	//方差分析页面初始化
	modelAnova = new QStandardItemModel();
	modelAnova->setColumnCount(factorNames.size()+1);
	QStringList header = factorNames;
	header.push_front(QString::fromLocal8Bit("已选结果"));
	modelAnova->setHorizontalHeaderLabels(header);
	ui.tableView_4->setModel(modelAnova);   //将数据模型与TableView绑定
	ui.tableView_4->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
	ui.tableView_4->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
	ui.tableView_4->setAlternatingRowColors(true);//隔行变色  
	ui.tableView_4->setSelectionBehavior(QAbstractItemView::SelectRows);//设置选中时为整行选中   
	ui.tableView_4->verticalHeader()->setHidden(false);//设置显示每行序号


	QString resultFileName = m_TaskDataFolderPath + "\\avr_res.txt";
	QFile res_file(resultFileName);
	//没有这个文件，说明没有结果，退出
	if (!res_file.open(QIODevice::ReadOnly))
		return;
	QTextStream res_in(&res_file);
	QString t_line;
	QStringList t_list;
	QVector<QStringList> res_data;  //结果文件内容
	while (!res_in.atEnd())
	{
		t_line = res_in.readLine().simplified();
		t_list = t_line.split(' ');
		res_data.append(t_list);
	}

	ui.tableWidget_4->setRowCount(res_data.size());
	ui.tableWidget_4->setColumnCount(res_data[0].length());
	//设置表头为因素名
	QStringList resHead = { QString::fromLocal8Bit("结果1"),QString::fromLocal8Bit("结果2"), QString::fromLocal8Bit("结果3"), QString::fromLocal8Bit("结果4"),
		QString::fromLocal8Bit("结果5"), QString::fromLocal8Bit("结果6"), QString::fromLocal8Bit("结果7"), QString::fromLocal8Bit("结果8") };
	ui.tableWidget_4->setHorizontalHeaderLabels(resHead);

	//表格内容
	for (int i = 0; i < res_data.size(); i++)
	{
		std::vector<std::pair<int, float>> rowAvrRes_anova;
		std::vector<double>rowAvrRes_pca;
		for (int j = 0; j < res_data[i].count(); j++)
		{
			ui.tableWidget_4->setItem(i, j, new QTableWidgetItem(res_data[i][j]));
			float temp = res_data[i][j].toFloat();
			rowAvrRes_anova.push_back({ i,temp });
			double temp1 = res_data[i][j].toDouble();
			rowAvrRes_pca.push_back(temp1);

		}
		vAvrRes_anova.push_back(rowAvrRes_anova);
		vAvrRes_pca.push_back(rowAvrRes_pca);
 	}
}

void FactorTableWidget::OndisplayAll(const QString &TaskDataFolderPath, const QString& TaskStatu)
{
	//显示因素水平表
	m_path_FL = TaskDataFolderPath + "\\factor_level_table.txt";
	m_TaskDataFolderPath = TaskDataFolderPath;
	ui.lineEdit->setText(m_path_FL);
	
	//工况表、想定表路径，默认显示第一个想定表
	QString FilePath_GK = TaskDataFolderPath + "\\gk.txt";
	QString FilePath_XD = TaskDataFolderPath + "\\xd_0.txt";
	
	if (TaskStatu == QString::fromLocal8Bit("工况表已生成"))
	{
		OndisplayTxt_GK(FilePath_GK);//因在显示工况表时更新当前任务的因素列表，故先调用
		OndisplayTxt_FL(m_path_FL);
		ui.pushButton_3->setEnabled(false);  //导入因素水平表按钮不可用
		ui.pushButton->setEnabled(false);  //生成工况按钮不可用
		return;
	}
	else if (TaskStatu == QString::fromLocal8Bit("想定表已生成"))
	{
		OndisplayTxt_GK(FilePath_GK);
		OndisplayTxt_FL(m_path_FL);
		FilePath_XD = "C://Users//zhang//Desktop//LargeSampleSimulationUI_0630//LargeSampleSimulationUI//data//XD0.txt";      //测试用
		OndisplayTxt_XD(FilePath_XD);
		ui.pushButton_3->setEnabled(false);  //导入因素水平表按钮不可用
		ui.pushButton->setEnabled(false);  //生成工况按钮不可用
		ui.pushButton_2->setEnabled(false);  //生成想定按钮不可用
		return;
	}
	else if (TaskStatu == QString::fromLocal8Bit("开始计算")) 
	{
		OndisplayTxt_GK(FilePath_GK);
		OndisplayTxt_FL(m_path_FL);
		FilePath_XD = "C://Users//zhang//Desktop//LargeSampleSimulationUI_0630//LargeSampleSimulationUI//data//XD0.txt";      //测试用
		OndisplayTxt_XD(FilePath_XD);
		ui.pushButton_3->setEnabled(false);  //导入因素水平表按钮不可用
		ui.pushButton->setEnabled(false);  //生成工况按钮不可用
		ui.pushButton_2->setEnabled(false);  //生成想定按钮不可用
		ui.pushButton_4->setEnabled(false);  //确认执行按钮不可用
		ui.pushButton_5->setEnabled(false);  //效能评估按钮不可用
		return;
	}
	else   //计算完成
	{
		OndisplayTxt_GK(FilePath_GK);
		OndisplayTxt_FL(m_path_FL);
		FilePath_XD = "C://Users//zhang//Desktop//LargeSampleSimulationUI_0630//LargeSampleSimulationUI//data//XD0.txt";      //测试用
		OndisplayTxt_XD(FilePath_XD);
		OndisplayTxt_avr_res();
		ui.pushButton_3->setEnabled(false);  //导入因素水平表按钮不可用
		ui.pushButton->setEnabled(false);  //生成工况按钮不可用
		ui.pushButton_2->setEnabled(false);  //生成想定按钮不可用
		ui.pushButton_4->setEnabled(false);  //确认执行按钮不可用
		return;
	}

}


void FactorTableWidget::OnActionRun()
{
	emit(StartRun(m_TaskDataFolderPath, curXDNums, curSendWindowLen));
	taskStatus = QString::fromLocal8Bit("开始计算");
	emit(changeTaskStatus(curTaskId, taskStatus));
}


void FactorTableWidget::OnActionPlotShow()
{
	//打开界面时更新当前任务数据文件夹路径
	//点击按钮 判断按钮所在行数 即结果表文件名中的序号
	//获取按钮的指针
	QPushButton *pushButton_ = dynamic_cast<QPushButton*>(this->sender());
	if (NULL == pushButton_)
	{
		return;
	}

	// 获取该按钮所在表格的行号
	QString row = pushButton_->property("row").toString();
	QString fileName = m_TaskDataFolderPath + "\\res_plot_" + row + ".txt";

	plot->show();
	plot->addPicture(fileName);
}

void FactorTableWidget::OnEfficiencyEvaluSlots()
{
	ui.tabWidget->setCurrentIndex(3);
	OndisplayTxt_avr_res();
	PcaAnalysis();
	std::vector<float> va;
	VarianceAnalysis(0, 8, 8, va);
	CorrelationAnalysis();
}

void FactorTableWidget::OnAnovaShow() 
{
	int celectResIdx = ui.selectResBox->currentIndex();
	int sampleNum = ui.lineEdit_sampleNum->text().toInt();
	int minSampleSize = ui.lineEdit_minSampleSize->text().toInt();

	std::vector<float> anov_res;
	if(!VarianceAnalysis(celectResIdx, sampleNum, minSampleSize, anov_res))
		QMessageBox::warning(NULL, QString::fromLocal8Bit("方差分析失败"), QString::fromLocal8Bit("样本容量不符合要求，请尝试调整相关设置"));
	//将当前绘制文件名添加到右侧显示列表中
	QList<QStandardItem*> add_items;
	add_items << new QStandardItem(ui.selectResBox->currentText());
	for (auto insert_data : anov_res) {
		add_items << new QStandardItem(QString::number(insert_data));
	}
	
	modelAnova->appendRow(add_items);
}

/* Description:	进行单因素方差分析
 * Input:		int selectedResId  要进行方差分析的结果序号
				int sampleNum	   对结果样本分组的个数
				int minSampleSize  每个样本组的最小容量
 * Output:		vector<float>& res 方差分析结果，存储当前所选结果对应的所有因素的p值
 * Return:  	计算成功返回true,计算失败返回false
 * Others:   */
bool FactorTableWidget::VarianceAnalysis(int selectedResId, int sampleNum, int minSampleSize, std::vector<float>& res)
{
	//对结果数组按指定的某个结果（序号为selectedResId）的大小排序
	std::sort(vAvrRes_anova.begin(), vAvrRes_anova.end(),
		[selectedResId](std::vector<std::pair<int, float>> a, std::vector<std::pair<int, float>> b) {return a[selectedResId].second < b[selectedResId].second; });

	std::vector<std::vector<int>> resHash(sampleNum);	//二维数组，所有结果按样本分组后，其序号存储于此
	float minRes = vAvrRes_anova[0][selectedResId].second;
	float maxRes = vAvrRes_anova[vAvrRes_anova.size() - 1][selectedResId].second;
	float step = (maxRes - minRes + 0.0001) / sampleNum;

	for (int i = 0; i < vAvrRes_anova.size(); i++) {
		float tmpRes = vAvrRes_anova[i][selectedResId].second;
		for (int sampleIdx = 0; sampleIdx < sampleNum; sampleIdx++) {
			if (tmpRes >= minRes + sampleIdx * step && tmpRes < minRes + (sampleIdx + 1)*step) {
				resHash[sampleIdx].emplace_back(i);
				break;
			}
		}
	}
	//将样本按频数排序
	std::sort(resHash.begin(), resHash.end(), [](std::vector<int>a, std::vector<int>b) {return a.size() < b.size(); });

	bool findFlag = false;
	int sampleSize = 0;
	int beginSampleIdx = sampleNum - 1;
	//对已排序的样本进行遍历，找到第一个超过样本最小容量minSampleSize的样本，记录
	for (int i = 0; i < sampleNum; i++) {
		if (resHash[i].size() >= minSampleSize) {
			findFlag = true;
			sampleSize = resHash[i].size();
			beginSampleIdx = i;
			break;
		}
	}

	//若符合要求的样本个数小于等于1，则无法进行方差分析，退出
	if (beginSampleIdx >= sampleNum - 1)
		return false;

	
	for (int factorIdx = 0; factorIdx < factorNames.size(); factorIdx++) {
		std::vector<std::vector<float>> data;	//方差分析的输入，每个样本中元素对应的水平

		//将符合条件（即样本大小满足要求）的样本对应的水平赋值给data
		for (int idx = beginSampleIdx; idx < sampleNum; idx++) {
			std::vector <float>tmp;
			for (int i = 0; i < sampleSize; i++) {
				int gkId = vAvrRes_anova[resHash[idx][i]][selectedResId].first; //所对应的工况id
				tmp.emplace_back(GKData[gkId][factorIdx]);
			}
			data.emplace_back(std::move(tmp));
		}
		//进行方差分析
		anov_result anovRes = anova(data);
		res.emplace_back(anovRes.f);
	}
	return true;
}

void FactorTableWidget::closeEvent(QCloseEvent *)
{
	emit(CloseFactorTbaleWidget());
}

void FactorTableWidget::PcaAnalysis()
{
	//Eigen::MatrixXd matrix(curXDNums, resCol);
	Eigen::MatrixXd matrix(8, 8);     //测试用
	//for (int i = 0; i < curXDNums; i++)
	//	matrix.row(i) = VectorXd::Map(&vAvrRes[i][0], vAvrRes[i].size());
	for (int i = 0; i < matrix.rows(); ++i)
	{
		for (int j = 0; j < matrix.cols(); ++j)
		{
			matrix(i, j) = vAvrRes_pca[i][j];
		}
	}


	double retained_variance = 0.95;//选择足够多的主成分以保证保留的特征值之和占总特征值之和的比例至少为0.95（即损失率不超过5%）
	pca_result = pca->PCA(matrix, retained_variance);

	////结果写文件
	////cout << "主成分:\n" << pca_result.transformed_data << endl;
	//QString transformed_dataFileName = m_TaskDataFolderPath + "\\transformed_data.txt";
	//std::ofstream fout1(transformed_dataFileName.toStdString(), std::ios::out);
	//fout1 << pca_result.transformed_data << std::endl;
	//fout1.flush();
	//fout1.close();
	////cout << "综合得分:\n" << pca_result.score << endl;
	//QString scoreFileName = m_TaskDataFolderPath + "\\score.txt";
	//std::ofstream fout2(scoreFileName.toStdString(), std::ios::out);
	//fout2 << pca_result.score << std::endl;
	//fout2.flush();
	//fout2.close();

	//主成分结果、综合得分显示 ------ tableWidget_5 
	ui.tabWidget_2->setCurrentIndex(0);
	ui.tableWidget_5->setAlternatingRowColors(true);//隔行变色
	ui.tableWidget_5->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);//行高自动填充
	ui.tableWidget_5->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//列宽自动填充
	int rowsCount = pca_result.transformed_data.rows();
	int cloumCount = pca_result.transformed_data.cols();
	ui.tableWidget_5->setRowCount(rowsCount + 1);
	ui.tableWidget_5->setColumnCount(cloumCount + 1);
	QStringList headerList_5;

	//表头
	for (int i = 0; i < cloumCount; i++)
	{
		QString headerStr = QString::fromLocal8Bit("主成分") + QString::number(i + 1);
		headerList_5.append(headerStr);
	}
	headerList_5.append(QString::fromLocal8Bit("综合得分"));
	ui.tableWidget_5->setHorizontalHeaderLabels(headerList_5);
	//表格内容
	for (int i = 0; i < rowsCount; ++i)
	{
		for (int j = 0; j < cloumCount; ++j)
		{
			ui.tableWidget_5->setItem(i, j, new QTableWidgetItem(QString::number(pca_result.transformed_data(i, j))));
		}
		ui.tableWidget_5->setItem(i, cloumCount, new QTableWidgetItem(QString::number(pca_result.score(i))));
	}
	//插入排序按钮
	QPushButton* btn_score = new QPushButton(QString::fromLocal8Bit("排序"));
	ui.tableWidget_5->setCellWidget(rowsCount, cloumCount, btn_score);
	connect(btn_score, SIGNAL(clicked()), this, SLOT(OnActionSort()));
	return;
}

void FactorTableWidget::OnActionSort()
{
	VectorXi ind;
	VectorXd sorted_score;
	pca->sort_vec(pca_result.score, sorted_score, ind);//综合得分排序，从大到小
	//cout << "综合得分排序：\n" << sorted_score << endl;
	//cout << "排序后各元素对应的原始得分中的位置：\n" << ind << endl;
	MatrixXd sorted_transformed_data(pca_result.transformed_data.rows(), pca_result.transformed_data.cols());
	for (int i = 0; i < pca_result.transformed_data.rows(); ++i)
	{
		for (int j = 0; j < pca_result.transformed_data.cols(); ++j)
		{
			sorted_transformed_data(i, j) = pca_result.transformed_data(ind(i), j);
			ui.tableWidget_5->setItem(i, j, new QTableWidgetItem(QString::number(sorted_transformed_data(i, j))));
		}
		ui.tableWidget_5->setItem(i, pca_result.transformed_data.cols(), new QTableWidgetItem(QString::number(sorted_score(i))));
	}

}

void FactorTableWidget::CorrelationAnalysis()
{
	ui.tabWidget_2->setCurrentIndex(1);
	ui.tableWidget_6->setAlternatingRowColors(true);//隔行变色
	ui.tableWidget_6->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);      //行高自动填充
	ui.tableWidget_6->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);  //列宽自动填充
	int rowsCount = pca_result.corCoefficient.rows();
	int cloumCount = pca_result.corCoefficient.cols();
	ui.tableWidget_6->setRowCount(rowsCount);
	ui.tableWidget_6->setColumnCount(cloumCount);
	QStringList horizontalHeaderList;
	//corCoefficient 转成二维vector
	std::vector< std::vector<double> > vCorCoefficient(rowsCount, std::vector<double>(cloumCount));
    std::vector<std::string> vNames;
	//表头
	for (int i = 0; i < cloumCount; i++){
		QString headerStr = QString::fromLocal8Bit("结果") + QString::number(i + 1);
		horizontalHeaderList.append(headerStr);
		std::string vNames_str = headerStr.toLocal8Bit();
		vNames.push_back(vNames_str);
	}
	ui.tableWidget_6->setHorizontalHeaderLabels(horizontalHeaderList);
	ui.tableWidget_6->setVerticalHeaderLabels(horizontalHeaderList);
	for (int i = 0; i < rowsCount; i++){                                   
		for (int j = 0; j < cloumCount; j++){
			vCorCoefficient[i][j] = pca_result.corCoefficient(i, j);
			ui.tableWidget_6->setItem(i, j, new QTableWidgetItem(QString::number(pca_result.corCoefficient(i, j))));
		}
	}
	ui.widget_heatMap->drawHeatMap(vCorCoefficient, vNames);
}
